var renderer; //渲染器
var width; //页面宽度
var height; //页面高度
var raycaster = new THREE.Raycaster(); //光线碰撞检测器
var mouse = new THREE.Vector2(); //存储鼠标坐标或者触摸坐标
var isRotating = false; //魔方是否正在转动
var intersect; //碰撞光线穿过的元素
var normalize; //触发平面法向量
var startPoint; //触发点
var movePoint;
var minCubeIndex;
var initStatus = []; //魔方初始状态
var startFaceNo = 0;
var currentFaceNo = 0;
var endFaceNo = 3;
//魔方转动的六个方向
const XLine = new THREE.Vector3(1, 0, 0); //X轴正方向
const XLineAd = new THREE.Vector3(-1, 0, 0); //X轴负方向
const YLine = new THREE.Vector3(0, 1, 0); //Y轴正方向
const YLineAd = new THREE.Vector3(0, -1, 0); //Y轴负方向
const ZLine = new THREE.Vector3(0, 0, 1); //Z轴正方向
const ZLineAd = new THREE.Vector3(0, 0, -1); //Z轴负方向
const CubeParams = { //魔方参数
    x: 0,
    y: 0,
    z: 0,
    num: 3,
    len: 50,
    //[右,左,上,下,前,后]
    colors: ['yellow', 'red', 'blue', 'green', 'white', 'pink']
};

//随机旋转，用于打乱魔方
function randomRotate() {
    if (!isRotating && !isAutoReset) {
        var stepNum = parseInt(20 * Math.random()) + 1; //保证至少转动一步
        //var stepNum = 0;
        console.log('random rotate ' + stepNum);
        var funcArr = [R, U, F, B, L, D, r, u, f, b, l, d];
        var stepArr = [];
        for (var i = 0; i < stepNum; i++) {
            var num = parseInt(Math.random() * funcArr.length);
            stepArr.push(funcArr[num]);
        }
        runMethodAtNo(stepArr, 0, 0);
    }

    // aa=takeChargeAsChiefOf();
    // console.log("aa")
    // console.log(aa)
}


//自动还原第一版
var isAutoReset = false;
var currentStep = 1;
var bottomColor;
var topColor;
var startTime = 0;
var endTime = 0;
var stepCount = 0;

function autoResetV1(cubes) {
    if (!checkStep8() && !isRotating) {
        console.log('start autoResetV1');
        startTime = window.performance.now();
        console.log('start at:' + startTime);
        stepCount = 0;
        isAutoReset = true;

        var topCenter = getCubeByIndex(10); //获取上表面中心小方块
        // 10 是上表面 中心 怎么定义啊
        topColor = getFaceColorByVector(topCenter, YLine); //获取上表面颜色
        bottomColor = getOppositeColor(topColor); //获取上表面颜色对应色

        if (checkStep7()) {
            currentStep = 8;
            console.log('start step8');
            step8();
            // step8 就结束了吧
        } else if (checkStep6()) {
            currentStep = 7;
            console.log('start step7');
            step7();
        } else if (checkStep5()) {
            currentStep = 6;
            console.log('start step6');
            step6();
        } else if (checkStep4()) {
            currentStep = 5;
            console.log('start step5');
            step5();
        } else if (checkStep3()) {
            currentStep = 4;
            startFaceNo = 0;
            currentFaceNo = 0;
            endFaceNo = 3;
            console.log('start step4');
            step4();
        } else if (checkStep2()) {
            currentStep = 3;
            console.log('start step3');
            step3();
        } else if (checkStep1()) {
            currentStep = 2;
            console.log('start step2');
            step2();
        } else {
            currentStep = 1;
            console.log('start step1');
            step1();
        }
    } else {
        console.log('already reset');
        document.getElementById("lazer").style.display = "block";

    }
}

function lazerDisplay() {
    document.getElementById("lazer").style.display = "block";
}
//第八步 顶角归位
function step8() {
    if (checkStep8()) {
        isAutoReset = false;
        endTime = window.performance.now();
        console.log('end at:' + endTime);
        console.log('total times:' + (endTime - startTime));
        console.log('total steps:' + stepCount);
        console.log('end autoResetV1');
        // ok
        lazerDisplay();
        return;
    }

    step8Case1(0);
    step8Case1(1);
    step8Case1(2);
    step8Case1(3);

    step8Case2(0);
    step8Case2(1);
    step8Case2(2);
    step8Case2(3);

    step8Case3();

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step8');
    }
}
//判断顶角归位 是否完成
function checkStep8Item(indexs, line) {
    if (indexs.length > 0) {
        var arr = getCubeByIndexs(indexs);
        // 第一个方块 arr[0]
        var color = getFaceColorByVector(arr[0], line)
        for (var i = 1; i < arr.length; i++) {
            if (getFaceColorByVector(arr[i], line) != color) {
                return false;
            }
        }
    }
    return true;
}

function checkStep8() {
    var result = true;
    var indexs1 = [1, 0, 2, 3, 4, 5, 6, 7, 8];
    // z 的 1 面
    result = checkStep8Item(indexs1, ZLine);
    if (!result) {
        // 不对
        return result;
    }

    var indexs2 = [11, 14, 17, 20, 23, 26, 2, 5, 8]
    result = checkStep8Item(indexs2, XLine);
    // x 1
    if (!result) {
        return result;
    }

    // z 3

    var indexs3 = [19, 18, 21, 22, 24, 25, 20, 23, 26];
    result = checkStep8Item(indexs3, ZLineAd);
    if (!result) {
        return result;
    }

    var index4 = [9, 0, 3, 6, 12, 15, 18, 21, 24];
    // x3
    result = checkStep8Item(index4, XLineAd);
    if (!result) {
        return result;
    }

    return result;
}

let sliceX1 = [11, 14, 17, 20, 23, 26, 2, 5, 8];
let sliceX2 = [10, 13, 16, 19, 22, 25, 1, 4, 7];
let sliceX3 = [9, 12, 15, 18, 21, 24, 0, 3, 6];
// let sliceX3 = [8, 11, 14, 17, 20, 23, -1, 2, 5];

let sliceZ3 = [19, 18, 21, 22, 24, 25, 20, 23, 26];
let sliceZ2 = [10, 9, 12, 13, 15, 16, 11, 14, 17];
let sliceZ1 = [1, 0, 3, 4, 6, 7, 2, 5, 8];


let sliceY1 = [0,1,2,9,10,11,18,19,20];
let sliceY2 = [3, 4, 5, 12, 13, 14, 21, 22, 23];
let sliceY3 =  [6, 7, 8, 15, 16, 17, 24, 25, 26];


function rotate801(rotateNum) {
    //RRBBRFrBBRfR
    var arr = [R, R, B, B, R, F, r, B, B, R, f, R];
    runMethodAtNo(arr, 0, rotateNum);
}

function rotate802(rotateNum) {
    //LLBBlfLBBlFl
    var arr = [L, L, B, B, l, f, L, B, B, l, F, l];
    runMethodAtNo(arr, 0, rotateNum);
}
//顶角归位 第一种情况
function step8Case1(rotateNum) {
    if (!isRotating) {
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube20 = getCubeByIndex(20, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube2, xLine) == getFaceColorByVector(cube20, xLine) &&
            getFaceColorByVector(cube2, xLine) != getFaceColorByVector(cube11, xLine)) {
            rotate801(rotateNum);
        }
    }
}
//顶角归位 第二种情况
// rotateNum 是什么意义呢
function step8Case2(rotateNum) {
    if (!isRotating) {
        var cube0 = getCubeByIndex(0, rotateNum);
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube20 = getCubeByIndex(20, rotateNum);
        // 这是最上面的 几个 L 的格子吗
        // 是顺时针 旋转吗
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        // 某一个的 所有的  xline 都是 一样的话 就是独当一面了
        if (getFaceColorByVector(cube0, zLine) == getFaceColorByVector(cube20, xLine) &&
            getFaceColorByVector(cube1, zLine) == getFaceColorByVector(cube2, zLine) &&
            getFaceColorByVector(cube11, xLine) == getFaceColorByVector(cube20, xLine) &&
            getFaceColorByVector(cube0, zLine) != getFaceColorByVector(cube1, zLine) &&
            getFaceColorByVector(cube20, xLine) != getFaceColorByVector(cube20, xLine)) {
            rotate802(rotateNum);
        }
    }
}

// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];

// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];
// let  zideZ=[0,1,2,3,4,5,6,7,8];

// 独当一面
function takeChargeAsChiefOf() {
    // var cube0 = getCubeByIndex(0,rotateNum);
    // var cube1 = getCubeByIndex(1,rotateNum);
    // var cube2 = getCubeByIndex(2,rotateNum);
    // var cube11 = getCubeByIndex(11,rotateNum);
    // var cube20 = getCubeByIndex(20,rotateNum);
    // 0 1 -- 8

    // let cubesLst = [];
    // for (let i = 0; i < 27; i++) {
    //     cubesLst.append(getCubeByIndex(i));
    //     // cubesLst[i]= getCubeByIndex(i);
    // }

    // let cubesLst=getCubeLst();
    //
    // let side1 = [];
    // for (let i = 0; i < 9; i++) {
    //     // side1.append(i);
    //     side1.push(i);
    // }


    // var zLine = rotateAxisByYLine(ZLine);
    // 返回自己可以吗
    // var zLine =ZLine;
    // let cube0Color=getFaceColorByVector(side1[0], zLine);
    // for (let cube of side1) {
    //     getFaceColorByVector(cube, zLine)
        
    // }
    // for (let i = 0; i < side1.length; i++) {
    //     const colorOfCube = side1[i];
    //     if(colorOfCube!=cube0Color){
            
    //     }
        
    // }

    // sideSameColor(ZLine,side1);
    // let slice0 = getSlice(0);
    // let slice0 = getZSlice(1);
    // let slice0 = getZSlice(2);
    // // if(sideSameColor(ZLine,slice0))
    // for (let i = 1; i <=3; i++) {
    //    let slice= getZSlice(i);
    //    if(slice)
    //        sideSameColor(ZLine,slice)
    //     if(getZSlice(i))
    // }

    //
    // sliceX3.forEach(o=>{
    //     console.log(o-2);
    // })

    // sideSameColor(ZLine, getZSlice(1))||
    // sideSameColor(ZLineAd, getZSlice(3))||

    // var cube20 = getCubeByIndex(20);
    // 怎么获得 cube
    // 为什么会打印


   let haveSliceSame=

       // sideSameColor(ZLine, getCubeLst(sliceZ1))||
       // sideSameColor(ZLineAd, sliceZ3)||
       //  sideSameColor(XLine, sliceX1)||
       //  sideSameColor(XLineAd, sliceX3)||
       //  sideSameColor(YLine, sliceY1)||
       //  sideSameColor(YLineAd, sliceY3);

       // 就是 根据法向量和 这一片的那些方块，去看颜色是不是都一样的
    sideSameColor(ZLine, getCubeLst(sliceZ1))||
    sideSameColor(ZLineAd, getCubeLst(sliceZ3))||
    sideSameColor(XLine, getCubeLst(sliceX1))||
    sideSameColor(XLineAd, getCubeLst(sliceX3))||
    sideSameColor(YLine, getCubeLst(sliceY1))||
    sideSameColor(YLineAd,getCubeLst( sliceY3));

    return haveSliceSame;

}

function getCubeLst(indexes){
    let cubeLst=[];
    for (let idx of indexes) {
        // idx
        cubeLst.push(  getCubeByIndex(idx));
    }
    return cubeLst;

}
let xSlice=[]
// function getSide(startIdx){
//   for
// }

function getSlice(startIdx){
    let  idx=startIdx;
    let slice = [];
  for (let i = 0; i < 9; i++) {
    //   const element = array[i];
    // slice.append(idx++);
    slice.push(idx++);
  }
  return slice;
}


function getZSlice(layer){
    let idx=layer*9-9;
    return  getZSliceOfCornerIdx(idx);
    // let  idx=startIdx;
    // let slice = [];
    // for (let i = 0; i < 9; i++) {
    //     //   const element = array[i];
    //     // slice.append(idx++);
    //     slice.push(idx++);
    // }
    // return slice;
}


function getZSliceOfCornerIdx(startIdx){
    let  idx=startIdx;
    let slice = [];
    for (let i = 0; i < 9; i++) {
        //   const element = array[i];
        // slice.append(idx++);
        slice.push(idx++);
    }
    return slice;
}


function getYSlice(idx){
    // let  idx=startIdx;
    let slice = [];
    // for (let i = idx; i < 9; i+=9) {
    //     //   const element = array[i];
    //     // slice.append(idx++);
    //     slice.push(idx++);
    // }
    // let  rowStart;
    // if(idx==1){
    //     let  rowStart=0;
    // }else if(idx===2){
    //     let  rowStart=3;
    // }
    let  rowStart=idx*3-3;
    // let  rowStart=idx;
    for (let i = 0; i <3 ; i++) {
        // let row=0;
       //  slice
       // row= getRow(rowStart);
        // slice.push(...row);
        putRow(rowStart,slice);
        rowStart+=9;
    }
    return slice;
}

function  putRow(rowStart,slice) {
    // let  row=[];
    idx=rowStart;
    for (let i = 0; i <3 ; i++) {
        slice.push(idx++);
    }
    // return row;
}

function  getRow(rowStart) {
    let  row=[];
    idx=rowStart;
    for (let i = 0; i <3 ; i++) {
        row.push(idx++);
    }
    return row;
}

function getSideZ(){
    let side1 = [];
    for (let i = 0; i < 9; i++) {
        // side1.append(i);
        side1.push(i);
    }
    return side1;

    // let cubesLst = [];
    // for (let i = 0; i < 27; i++) {
    //     cubesLst.append(getCubeByIndex(i));
    //     // cubesLst[i]= getCubeByIndex(i);
    // }

    // return cubesLst;
}

function getCubeLst(){
    let cubesLst = [];
    for (let i = 0; i < 27; i++) {
        // cubesLst.append(getCubeByIndex(i));
        cubesLst.push(getCubeByIndex(i));
        // cubesLst[i]= getCubeByIndex(i);
    }

    return cubesLst;
}

function sideSameColor(axis,side){
    // var zLine =ZLine;
    // let cube0Color=getFaceColorByVector(side1[0], zLine);

    // var zLine =ZLine;
    let cube0Color=getFaceColorByVector(side[0], axis);

    // for (let cube of side1) {
    //     getFaceColorByVector(cube, zLine)
        
    // }
    // for (let i = 0; i < side1.length; i++) {
    //     const colorOfCube = side1[i];
    //     if(colorOfCube!=cube0Color){
            
    //     }
        
    // }

    // for (let cube of side1) {
    //     getFaceColorByVector(cube, zLine)
        
    // }

    for (let i = 0; i < side.length; i++) {
        // const colorOfCube = side[i];
        // console.log("side")
        // console.log(side)
        // 可不敢乱打印 好卡
        const colorOfCube   =getFaceColorByVector(side[i], axis);
        if(colorOfCube!==cube0Color){
            return false;
        
        }
        
    }
    return true;
}

//顶角归位 第三种情况
function step8Case3() {
    if (!isRotating) {
        var cube0 = getCubeByIndex(0);
        var cube2 = getCubeByIndex(2);
        var cube20 = getCubeByIndex(20);
        var cube18 = getCubeByIndex(18);
        if (getFaceColorByVector(cube0, ZLine) != getFaceColorByVector(cube2, ZLine) &&
            getFaceColorByVector(cube2, XLine) != getFaceColorByVector(cube20, XLine) &&
            getFaceColorByVector(cube20, ZLineAd) != getFaceColorByVector(cube18, ZLineAd) &&
            getFaceColorByVector(cube18, XLineAd) != getFaceColorByVector(cube0, XLineAd)) {
            rotate801(0);
        }
    }
}
//第七步 顶棱归位
function step7() {
    if (checkStep7()) {
        console.log('start step8');
        currentStep = 8;
        step8();
        return;
    }

    step7Case1(0);
    step7Case1(1);
    step7Case1(2);
    step7Case1(3);

    step7Case2(0);
    step7Case2(1);
    step7Case2(2);
    step7Case2(3);

    step7Case3();

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step7');
    }
}
//顶棱归位 第一种情况
function step7Case1(rotateNum) {
    if (!isRotating) {
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine4Color = getFaceColorByVector(cube4, zLine);
        if (getFaceColorByVector(cube1, zLine) != zLine4Color &&
            zLine4Color == getFaceColorByVector(cube11, xLine) &&
            zLine4Color != getFaceColorByVector(cube14, xLine)) {
            F(rotateNum, function () {
                F(rotateNum, function () {
                    U(rotateNum, function () {
                        r(rotateNum, function () {
                            L(rotateNum, function () {
                                F(rotateNum, function () {
                                    F(rotateNum, function () {
                                        R(rotateNum, function () {
                                            l(rotateNum, function () {
                                                U(rotateNum, function () {
                                                    F(rotateNum, function () {
                                                        F(rotateNum)
                                                    })
                                                })
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
            })
        }
    }
}
//顶棱归位 第二种情况
function step7Case2(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine1Color = getFaceColorByVector(cube1, zLine);
        if (zLine1Color != getFaceColorByVector(cube4, zLine) &&
            zLine1Color == getFaceColorByVector(cube14, xLine) &&
            zLine1Color != getFaceColorByVector(cube11, xLine)) {
            F(rotateNum, function () {
                F(rotateNum, function () {
                    u(rotateNum, function () {
                        r(rotateNum, function () {
                            L(rotateNum, function () {
                                F(rotateNum, function () {
                                    F(rotateNum, function () {
                                        R(rotateNum, function () {
                                            l(rotateNum, function () {
                                                u(rotateNum, function () {
                                                    F(rotateNum, function () {
                                                        F(rotateNum)
                                                    })
                                                })
                                            })
                                        })
                                    })
                                })
                            })
                        })
                    })
                })
            })
        }
    }
}
//顶棱归位 第三种情况（有两个对应的面顶棱完成，另外两个对应的面顶棱没有）
function step7Case3() {
    if (!isRotating && !checkStep7()) {
        u(0);
    }
}
//判断是否完成第七步 顶棱归位
function checkStep7() {
    if (!checkStep6()) {
        return false;
    }

    var cube1 = getCubeByIndex(1);
    var cube4 = getCubeByIndex(4);
    var cube11 = getCubeByIndex(11);
    var cube14 = getCubeByIndex(14);
    var cube19 = getCubeByIndex(19);
    var cube22 = getCubeByIndex(22);
    var cube9 = getCubeByIndex(9);
    var cube12 = getCubeByIndex(12);

    if (getFaceColorByVector(cube1, ZLine) != getFaceColorByVector(cube4, ZLine) ||
        getFaceColorByVector(cube11, XLine) != getFaceColorByVector(cube14, XLine) ||
        getFaceColorByVector(cube19, ZLineAd) != getFaceColorByVector(cube22, ZLineAd) ||
        getFaceColorByVector(cube9, XLineAd) != getFaceColorByVector(cube12, XLineAd)) {
        return false;
    }

    return true;
}
//第六步 顶角面位
function step6() {
    if (checkStep6()) {
        console.log('start step7');
        currentStep = 7;
        step7();
        return;
    }

    step6Case1(0);
    step6Case1(1);
    step6Case1(2);
    step6Case1(3);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step6');
    }
}

function rotate601(rotateNum) {
    //rULuRUlu
    var arr = [r, U, L, u, R, U, l, u];
    runMethodAtNo(arr, 0, rotateNum);
}

function rotate602(rotateNum) {
    //ULurUluR
    var arr = [U, L, u, r, U, l, u, R];
    runMethodAtNo(arr, 0, rotateNum);
}

function rotate603(rotateNum) {
    //RUrURUUr
    var arr = [R, U, r, U, R, U, U, r];
    runMethodAtNo(arr, 0, rotateNum);
}
//顶角面位 第一种、第二种和第三种情况
function step6Case1(rotateNum) {
    if (!isRotating) {
        var cube0 = getCubeByIndex(0, rotateNum);
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube20 = getCubeByIndex(20, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube0, zLine) == topColor &&
            getFaceColorByVector(cube2, xLine) == topColor) {
            rotate601(rotateNum);
        } else if (getFaceColorByVector(cube2, zLine) == topColor &&
            getFaceColorByVector(cube20, xLine) == topColor) {
            rotate602(rotateNum);
        } else if (getFaceColorByVector(cube0, zLine) == topColor) {
            rotate603(rotateNum);
        }
    }
}
//判断是否完成第六步 顶角面位
function checkStep6() {
    if (!checkStep5()) {
        return false;
    }

    var cube0 = getCubeByIndex(0);
    var cube2 = getCubeByIndex(2);
    var cube18 = getCubeByIndex(18);
    var cube20 = getCubeByIndex(20);
    if (getFaceColorByVector(cube0, YLine) != topColor ||
        getFaceColorByVector(cube2, YLine) != topColor ||
        getFaceColorByVector(cube18, YLine) != topColor ||
        getFaceColorByVector(cube20, YLine) != topColor) {
        return false;
    }
    return true;
}
//第五步 顶棱面位
function step5() {
    if (checkStep5()) {
        console.log('start step6');
        currentStep = 6;
        step6();
        return;
    }

    step5Case1(0);
    step5Case1(1);
    step5Case1(2);
    step5Case1(3);

    step5Case2(0);
    step5Case2(1);
    step5Case2(2);
    step5Case2(3);

    step5Case3(0);
    step5Case3(1);
    step5Case3(2);
    step5Case3(3);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step5');
    }
}

function rotate501(rotateNum, next) {
    //rufUFR
    var arr = [r, u, f, U, F, R];
    runMethodAtNo(arr, 0, rotateNum, next);
}

function rotate502(rotateNum, next) {
    //rfuFUR
    var arr = [r, f, u, F, U, R];
    runMethodAtNo(arr, 0, rotateNum, next);
}
//顶棱面位 第一种情况
function step5Case1(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube9 = getCubeByIndex(9, rotateNum);
        var cube19 = getCubeByIndex(19, rotateNum);
        var cube10 = getCubeByIndex(10, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube10, YLine) == topColor &&
            getFaceColorByVector(cube9, YLine) == topColor &&
            getFaceColorByVector(cube19, YLine) == topColor &&
            getFaceColorByVector(cube1, zLine) == topColor &&
            getFaceColorByVector(cube11, xLine) == topColor) {
            rotate501(rotateNum);
        }
    }
}
//顶棱面位 第二种情况
function step5Case2(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube19 = getCubeByIndex(19, rotateNum);
        var cube10 = getCubeByIndex(10, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube10, YLine) == topColor &&
            getFaceColorByVector(cube1, YLine) == topColor &&
            getFaceColorByVector(cube19, YLine) == topColor &&
            getFaceColorByVector(cube11, xLine) == topColor) {
            rotate501(rotateNum);
        }
    }
}
//顶棱面位 第三种情况
function step5Case3(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube10 = getCubeByIndex(10, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube10, YLine) == topColor &&
            getFaceColorByVector(cube1, zLine) == topColor &&
            getFaceColorByVector(cube11, xLine) == topColor) {
            rotate501(rotateNum, function () {
                U(rotateNum, function () {
                    rotate502(rotateNum);
                })
            });
        }
    }
}
//判断是否完成第五步 顶棱面位
function checkStep5() {
    if (!checkStep4()) {
        return false;
    }

    var cube1 = getCubeByIndex(1);
    var cube11 = getCubeByIndex(11);
    var cube9 = getCubeByIndex(9);
    var cube19 = getCubeByIndex(19);
    var cube10 = getCubeByIndex(10);
    if (getFaceColorByVector(cube10, YLine) != topColor ||
        getFaceColorByVector(cube1, YLine) != topColor ||
        getFaceColorByVector(cube11, YLine) != topColor ||
        getFaceColorByVector(cube9, YLine) != topColor ||
        getFaceColorByVector(cube19, YLine) != topColor) {
        return false;
    }

    return true;
}
//第四步 中棱归位
function step4() {
    if (checkStep4()) {
        console.log('start step5');
        currentStep = 5;
        step5();
        return;
    }

    step4Face(currentFaceNo);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step4');
    }
}

function rotate401(rotateNum, next) {
    if (rotateNum < 0) {
        rotateNum = 4 - Math.abs(rotateNum);
    }
    //rururURUR
    var arr = [r, u, r, u, r, U, R, U, R];
    runMethodAtNo(arr, 0, rotateNum, next);
}

function rotate401Opposite(rotateNum, next) {
    if (rotateNum < 0) {
        rotateNum = 4 - Math.abs(rotateNum);
    }
    //ruruRURUR
    var arr = [r, u, r, u, R, U, R, U, R];
    runMethodAtNo(arr, 0, rotateNum, next);
}

function rotate402(rotateNum, next) {
    if (rotateNum < 0) {
        rotateNum = 4 - Math.abs(rotateNum);
    }
    //FUFUFufuf
    var arr = [F, U, F, U, F, u, f, u, f];
    runMethodAtNo(arr, 0, rotateNum, next);
}

function rotate402Opposite(rotateNum, next) {
    if (rotateNum < 0) {
        rotateNum = 4 - Math.abs(rotateNum);
    }
    //FUFUfufuf
    var arr = [F, U, F, U, f, u, f, u, f];
    runMethodAtNo(arr, 0, rotateNum, next);
}
//中棱归位优先还原一个面
function step4Face(rotateNum) {
    if (!isRotating) {
        if (rotateNum > 3) {
            rotateNum = rotateNum - 4;
        }
        currentFaceNo = rotateNum;
        var cube3 = getCubeByIndex(3, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube5 = getCubeByIndex(5, rotateNum);
        var cube6 = getCubeByIndex(6, rotateNum);
        var cube9 = getCubeByIndex(9, rotateNum);
        var cube19 = getCubeByIndex(19, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube21 = getCubeByIndex(21, rotateNum);
        var cube23 = getCubeByIndex(23, rotateNum);

        var xLine = rotateAxisByYLine(XLine, rotateNum);
        // 他是怎么知道 rotateNum 和他的关系的 
        // 不管旋转多少 他都是 xLine 吗
        // 也就是这是 旋转之后的 xLine 吗
        // 那他就是他自己 ，是 0吗
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
        var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);

        var zLine4Color = getFaceColorByVector(cube4, zLine);
        var xLineAd6Color = getFaceColorByVector(cube6, xLineAd);
        var xLine14Color = getFaceColorByVector(cube14, xLine);

        if (getFaceColorByVector(cube3, zLine) != zLine4Color) {
            if (getFaceColorByVector(cube9, YLine) == zLine4Color &&
                (getFaceColorByVector(cube9, xLineAd) == xLineAd6Color || rotateNum == startFaceNo)) {
                rotate402(rotateNum - 1);
                return;
            } else if (getFaceColorByVector(cube9, xLineAd) == zLine4Color &&
                (getFaceColorByVector(cube9, YLine) == xLineAd6Color || rotateNum == startFaceNo)) {
                u(0, function () {
                    rotate401(rotateNum - 1);
                });
                return;
            } else if ((getFaceColorByVector(cube19, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube19, zLineAd) == xLineAd6Color || rotateNum == startFaceNo)) ||
                (getFaceColorByVector(cube19, zLineAd) == zLine4Color &&
                    (getFaceColorByVector(cube19, YLine) == xLineAd6Color || rotateNum == startFaceNo)) ||
                (getFaceColorByVector(cube11, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube11, xLine) == xLineAd6Color || rotateNum == startFaceNo)) ||
                (getFaceColorByVector(cube11, xLine) == zLine4Color &&
                    (getFaceColorByVector(cube11, YLine) == xLineAd6Color || rotateNum == startFaceNo)) ||
                (getFaceColorByVector(cube1, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube1, zLine) == xLineAd6Color || rotateNum == startFaceNo)) ||
                (getFaceColorByVector(cube1, zLine) == zLine4Color &&
                    (getFaceColorByVector(cube1, YLine) == xLineAd6Color || rotateNum == startFaceNo))) {
                U(0);
                return;
            } else if (getFaceColorByVector(cube5, zLine) == zLine4Color &&
                (getFaceColorByVector(cube5, xLine) == xLineAd6Color || rotateNum == startFaceNo)) {
                rotate401Opposite(rotateNum);
                return;
            } else if (getFaceColorByVector(cube3, xLineAd) == zLine4Color &&
                (getFaceColorByVector(cube3, zLine) == xLineAd6Color || rotateNum == startFaceNo)) {
                var tempNum = rotateNum - 1;
                rotate402(tempNum, function () {
                    U(tempNum, function () {
                        rotate401(tempNum);
                    });
                });
                return;
            } else if (getFaceColorByVector(cube23, xLine) == zLine4Color &&
                (getFaceColorByVector(cube23, zLineAd) == xLineAd6Color || rotateNum == startFaceNo)) {
                rotate402Opposite(rotateNum - 3);
                return;
            } else if (getFaceColorByVector(cube23, zLineAd) == zLine4Color &&
                (getFaceColorByVector(cube23, xLine) == xLineAd6Color || rotateNum == startFaceNo)) {
                rotate402Opposite(rotateNum - 3);
                return;
            } else if (getFaceColorByVector(cube5, xLine) == zLine4Color &&
                (getFaceColorByVector(cube5, zLine) == xLineAd6Color || rotateNum == startFaceNo)) {
                rotate402Opposite(rotateNum);
                return;
            } else if ((getFaceColorByVector(cube21, xLineAd) == zLine4Color || getFaceColorByVector(cube21, zLineAd) == zLine4Color) && rotateNum <= 0) {
                //除非是刚开始否则不能影响已经还原好的面
                rotate402Opposite(rotateNum - 2);
                return;
            }
        }
        if (getFaceColorByVector(cube5, zLine) != zLine4Color) {
            if (getFaceColorByVector(cube11, YLine) == zLine4Color &&
                (getFaceColorByVector(cube11, xLine) == xLine14Color || rotateNum != endFaceNo)) {
                rotate401(rotateNum);
                return;
            } else if (getFaceColorByVector(cube11, xLine) == zLine4Color &&
                (getFaceColorByVector(cube11, YLine) == xLine14Color || rotateNum != endFaceNo)) {
                U(0, function () {
                    rotate402(rotateNum);
                });
                return;
            } else if ((getFaceColorByVector(cube1, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube1, zLine) == xLine14Color || rotateNum != endFaceNo)) ||
                (getFaceColorByVector(cube1, zLine) == zLine4Color &&
                    (getFaceColorByVector(cube1, YLine) == xLine14Color || rotateNum != endFaceNo)) ||
                (getFaceColorByVector(cube9, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube9, xLineAd) == xLine14Color || rotateNum != endFaceNo)) ||
                (getFaceColorByVector(cube9, xLineAd) == zLine4Color &&
                    (getFaceColorByVector(cube9, YLine) == xLine14Color || rotateNum != endFaceNo)) ||
                (getFaceColorByVector(cube19, YLine) == zLine4Color &&
                    (getFaceColorByVector(cube19, zLineAd) == xLine14Color || rotateNum != endFaceNo)) ||
                (getFaceColorByVector(cube19, zLineAd) == zLine4Color &&
                    (getFaceColorByVector(cube19, YLine) == xLine14Color || rotateNum != endFaceNo))) {
                u(0);
                return;
            } else if (getFaceColorByVector(cube5, xLine) == zLine4Color &&
                (getFaceColorByVector(cube5, zLine) == xLine14Color || rotateNum != endFaceNo)) {
                rotate402Opposite(rotateNum);
                return;
            } else if ((getFaceColorByVector(cube21, xLineAd) == zLine4Color || getFaceColorByVector(cube21, zLineAd) == zLine4Color) && rotateNum <= 0) {
                //除非是刚开始否则不能影响已经还原好的面
                rotate402Opposite(rotateNum - 2);
                return;
            } else if (getFaceColorByVector(cube23, zLineAd) == zLine4Color && rotateNum == startFaceNo) {
                rotate402Opposite(rotateNum - 3);
                return;
            } else if (getFaceColorByVector(cube23, xLine) == zLine4Color &&
                (getFaceColorByVector(cube23, zLineAd) == xLine14Color || rotateNum != endFaceNo)) {
                rotate402Opposite(rotateNum - 3);
                return;
            }
        }

        if (getFaceColorByVector(cube3, zLine) != zLine4Color || getFaceColorByVector(cube5, zLine) != zLine4Color) {
            //某个面出现极端情况，以该面为起始面重新还原
            startFaceNo = currentFaceNo;
            if (startFaceNo > 0) {
                endFaceNo = startFaceNo - 1;
            } else {
                endFaceNo = 3;
            }
        } else {
            currentFaceNo++;
            if (currentFaceNo > 3) {
                currentFaceNo = 0;
            }
        }
        step4();
    }
}
//判断是否完成第四步 中棱归位
function checkStep4() {
    if (!checkStep3()) {
        return false;
    }

    var cube3 = getCubeByIndex(3);
    var cube4 = getCubeByIndex(4);
    var cube5 = getCubeByIndex(5);
    var zLine3Color = getFaceColorByVector(cube3, ZLine);
    if (getFaceColorByVector(cube4, ZLine) != zLine3Color ||
        getFaceColorByVector(cube5, ZLine) != zLine3Color) {
        return false;
    }

    var cube14 = getCubeByIndex(14);
    var cube23 = getCubeByIndex(23);
    var xLine5Color = getFaceColorByVector(cube5, XLine);
    if (getFaceColorByVector(cube14, XLine) != xLine5Color ||
        getFaceColorByVector(cube23, XLine) != xLine5Color) {
        return false;
    }

    var cube21 = getCubeByIndex(21);
    var cube22 = getCubeByIndex(22);
    var zLineAd23Color = getFaceColorByVector(cube23, ZLineAd);
    if (getFaceColorByVector(cube21, ZLineAd) != zLineAd23Color ||
        getFaceColorByVector(cube22, ZLineAd) != zLineAd23Color) {
        return false;
    }

    var cube12 = getCubeByIndex(12);
    var xLineAd3Color = getFaceColorByVector(cube3, XLineAd);
    if (getFaceColorByVector(cube12, XLineAd) != xLineAd3Color ||
        getFaceColorByVector(cube21, XLineAd) != xLineAd3Color) {
        return false;
    }

    return true;
}
//第三步底角归位
function step3() {
    if (checkStep3()) {
        console.log('start step4');
        currentStep = 4;
        startFaceNo = 0;
        endFaceNo = 3;
        step4();
        return;
    }
    step3Case1(0);
    step3Case1(1);
    step3Case1(2);
    step3Case1(3);

    step3Case2(0);
    step3Case2(1);
    step3Case2(2);
    step3Case2(3);

    step3Case3(0);
    step3Case3(1);
    step3Case3(2);
    step3Case3(3);

    step3Case4(0);
    step3Case4(1);
    step3Case4(2);
    step3Case4(3);

    step3Case5(0);
    step3Case5(1);
    step3Case5(2);
    step3Case5(3);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step3');
    }
}
//底角归位第一种情况
function step3Case1(rotateNum, startNum) {
    if (!isRotating) {
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube17 = getCubeByIndex(17, rotateNum);
        var cube8 = getCubeByIndex(8, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
        var zLine2Color = getFaceColorByVector(cube2, zLine);
        var yLine2Color = getFaceColorByVector(cube2, YLine);

        if (getFaceColorByVector(cube2, xLine) == bottomColor && !cube2.skipNext) {
            if (getFaceColorByVector(cube8, YLineAd) != bottomColor &&
                getFaceColorByVector(cube4, zLine) == zLine2Color &&
                getFaceColorByVector(cube7, zLine) == zLine2Color &&
                getFaceColorByVector(cube14, xLine) == yLine2Color &&
                getFaceColorByVector(cube17, xLine) == yLine2Color) {
                R(rotateNum, function () {
                    U(rotateNum, function () {
                        r(rotateNum)
                    })
                })
            } else {
                u(rotateNum, function () {
                    rotateNum++;
                    if (rotateNum >= 4) {
                        rotateNum = 0;
                    }
                    if (startNum != rotateNum) { //防止重复检测造成无限循环
                        if (startNum == null || startNum == undefined) {
                            startNum = rotateNum - 1;
                            step3Case1(rotateNum, startNum);
                        } else {
                            step3Case1(rotateNum, startNum);
                        }
                    } else {
                        var cube2 = getCubeByIndex(2, rotateNum);
                        cube2.skipNext = true; //下一次不进入判断
                        step3();
                    }
                })
            }
        }
    }
}
//底角归位第二种情况
function step3Case2(rotateNum, startNum) {
    if (!isRotating) {
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube17 = getCubeByIndex(17, rotateNum);
        var cube8 = getCubeByIndex(8, rotateNum);
        var yLine2Color = getFaceColorByVector(cube2, YLine);
        var xLine2Color = getFaceColorByVector(cube2, xLine);

        if (getFaceColorByVector(cube2, zLine) == bottomColor && !cube2.skipNext) {
            if (getFaceColorByVector(cube8, YLineAd) != bottomColor &&
                getFaceColorByVector(cube4, zLine) == yLine2Color &&
                getFaceColorByVector(cube7, zLine) == yLine2Color &&
                getFaceColorByVector(cube14, xLine) == xLine2Color &&
                getFaceColorByVector(cube17, xLine) == xLine2Color) {
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        F(rotateNum)
                    })
                })
            } else {
                u(rotateNum, function () {
                    rotateNum++;
                    if (rotateNum >= 4) {
                        rotateNum = 0;
                    }
                    if (startNum != rotateNum) { //防止重复检测造成无限循环
                        if (startNum == null || startNum == undefined) {
                            startNum = rotateNum - 1;
                            step3Case2(rotateNum, startNum);
                        } else {
                            step3Case2(rotateNum, startNum);
                        }
                    } else {
                        var cube2 = getCubeByIndex(2, rotateNum);
                        cube2.skipNext = true; //下一次不进入判断
                        step3();
                    }
                })
            }
        }
    }
}
//底角归位第三种情况
function step3Case3(rotateNum, startNum) {
    if (!isRotating) {
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
        var cube2 = getCubeByIndex(2, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube8 = getCubeByIndex(8, rotateNum);
        var cube17 = getCubeByIndex(17, rotateNum);
        var zLine2Color = getFaceColorByVector(cube2, zLine);
        var xLine2Color = getFaceColorByVector(cube2, xLine);

        if (getFaceColorByVector(cube2, YLine) == bottomColor && !cube2.skipNext) {
            if (getFaceColorByVector(cube8, YLineAd) != bottomColor &&
                getFaceColorByVector(cube14, xLine) == zLine2Color &&
                getFaceColorByVector(cube17, xLine) == zLine2Color &&
                getFaceColorByVector(cube4, zLine) == xLine2Color &&
                getFaceColorByVector(cube7, zLine) == xLine2Color) {
                //转换为第二种情况
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        u(rotateNum, function () {
                            F(rotateNum, function () {
                                U(rotateNum)
                            })
                        })
                    })
                })
            } else {
                u(rotateNum, function () {
                    rotateNum++;
                    if (rotateNum >= 4) {
                        rotateNum = 0;
                    }
                    if (startNum != rotateNum) { //防止重复检测造成无限循环
                        if (startNum == null || startNum == undefined) {
                            startNum = rotateNum - 1;
                            step3Case3(rotateNum, startNum);
                        } else {
                            step3Case3(rotateNum, startNum);
                        }
                    } else {
                        var cube2 = getCubeByIndex(2, rotateNum);
                        cube2.skipNext = true; //下一次不进入判断
                        step3();
                    }
                })
            }
        }
    }
}
//底角归位第四种情况
function step3Case4(rotateNum) {
    if (!isRotating) {
        var cube8 = getCubeByIndex(8, rotateNum);
        var cube17 = getCubeByIndex(17, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var zLine8Color = getFaceColorByVector(cube8, zLine);
        var yLineAd8Color = getFaceColorByVector(cube8, YLineAd);

        if (getFaceColorByVector(cube8, xLine) == bottomColor) {
            if (getFaceColorByVector(cube17, xLine) == zLine8Color &&
                getFaceColorByVector(cube14, xLine) == zLine8Color &&
                getFaceColorByVector(cube4, zLine) == yLineAd8Color &&
                getFaceColorByVector(cube7, zLine) == yLineAd8Color) {
                //转换为第一种情况
                f(rotateNum, function () {
                    U(rotateNum, function () {
                        F(rotateNum)
                    })
                })
            } else {
                //转换为第三种情况
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        F(rotateNum)
                    })
                })
            }
        }
    }
}
//底角归位第五种情况
function step3Case5(rotateNum) {
    if (!isRotating) {
        var cube8 = getCubeByIndex(8, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube14 = getCubeByIndex(14, rotateNum);
        var cube17 = getCubeByIndex(17, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine8Color = getFaceColorByVector(cube8, xLine);
        var yLineAd8Color = getFaceColorByVector(cube8, YLineAd);

        if (getFaceColorByVector(cube8, zLine) == bottomColor) {
            if (getFaceColorByVector(cube7, zLine) == xLine8Color &&
                getFaceColorByVector(cube4, zLine) == xLine8Color &&
                getFaceColorByVector(cube14, xLine) == yLineAd8Color &&
                getFaceColorByVector(cube17, xLine) == yLineAd8Color) {
                //转换为第二种情况
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        F(rotateNum, function () {
                            U(rotateNum)
                        })
                    })
                })
            } else {
                //转换为第三种情况
                R(rotateNum, function () {
                    u(rotateNum, function () {
                        r(rotateNum)
                    })
                })
            }
        }
    }
}

//判断是否完成第三步底角归位
function checkStep3Item(indexs, line) {
    if (indexs.length > 0) {
        var arr = getCubeByIndexs(indexs);
        for (var i = 1; i < arr.length; i++) {
            if (getFaceColorByVector(arr[i], line) != getFaceColorByVector(arr[0], line)) {
                return false;
            }
            if (getFaceColorByVector(arr[i], YLineAd) != bottomColor) {
                return false;
            }
        }
    }
    return true;
}

function checkStep3() {
    var result = true;
    var indexs1 = [4, 6, 7, 8];
    result = checkStep3Item(indexs1, ZLine);
    if (!result) {
        return result;
    }

    var indexs2 = [14, 8, 17, 26];
    result = checkStep3Item(indexs2, XLine);
    if (!result) {
        return result;
    }

    var indexs3 = [22, 24, 25, 26];
    result = checkStep3Item(indexs3, ZLineAd);
    if (!result) {
        return result;
    }

    var indexs4 = [12, 6, 15, 24];
    result = checkStep3Item(indexs4, XLineAd);
    if (!result) {
        return result;
    }

    return result;
}

//第二步底棱归位
function step2() {
    if (checkStep2()) {
        console.log('start step3');
        currentStep = 3;
        step3();
        return;
    }

    step2Case1(0);
    step2Case1(1);
    step2Case1(2);
    step2Case1(3);

    step2Case2(0);
    step2Case2(1);
    step2Case2(2);
    step2Case2(3);

    step2Case3(0);
    step2Case3(1);
    step2Case3(2);
    step2Case3(3);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step2');
    }
}
//底棱归位第一种情况
function step2Case1(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube4 = getCubeByIndex(4, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);

        if (getFaceColorByVector(cube1, YLine) == bottomColor) {
            if (getFaceColorByVector(cube1, zLine) == getFaceColorByVector(cube4, zLine)) {
                F(rotateNum, function () {
                    F(rotateNum);
                });
            } else {
                u(rotateNum, function () {
                    rotateNum++;
                    if (rotateNum >= 4) {
                        rotateNum = 0;
                    }
                    step2Case1(rotateNum);
                });
            }
        }
    }
}
//底棱归位第二种情况
function step2Case2(rotateNum) {
    if (!isRotating) {
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube8 = getCubeByIndex(8, rotateNum);
        var cube2 = getCubeByIndex(2, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        if (getFaceColorByVector(cube7, YLineAd) == bottomColor &&
            getFaceColorByVector(cube8, YLineAd) == bottomColor) {
            if (getCubeByIndex(cube2, xLine) != bottomColor) {
                R(rotateNum, function () {
                    u(rotateNum, function () {
                        r(rotateNum);
                    });
                })
            } else {
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        F(rotateNum);
                    });
                })
            }
        }
    }
}
//底棱归位第三种情况
function step2Case3(rotateNum) {
    if (!isRotating) {
        var cube7 = getCubeByIndex(7, rotateNum);
        var cube6 = getCubeByIndex(6, rotateNum);
        var cube0 = getCubeByIndex(0, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
        if (getFaceColorByVector(cube7, YLineAd) == bottomColor &&
            getFaceColorByVector(cube6, YLineAd) == bottomColor) {
            if (getFaceColorByVector(cube0, xLineAd) != bottomColor) {
                l(rotateNum, function () {
                    u(rotateNum, function () {
                        L(rotateNum)
                    });
                })
            } else {
                f(rotateNum, function () {
                    u(rotateNum, function () {
                        F(rotateNum);
                    });
                })
            }
        }
    }
}
/**
 * 判断是否完成第二部底棱归位（严格底十字）
 */
function checkStep2() {
    var indexs = [4, 7, 14, 17, 22, 25, 12, 15];
    var lines = [ZLine, XLine, ZLineAd, XLineAd];
    var arr = getCubeByIndexs(indexs);
    for (var i = 0; i < arr.length; i++) {
        var no = parseInt(i / 2);
        var color1 = getFaceColorByVector(arr[i], lines[no]);
        if (color1 == topColor || color1 == bottomColor) { //不能为顶色和底色
            return false;
        }
        if (i % 2 == 0) {
            var color2 = getFaceColorByVector(arr[i + 1], lines[no]);
            if (color1 != color2) { //两两相同
                return false;
            }
        }
    }

    //强制底十字
    for (var i = 1; i < arr.length; i = i + 2) {
        var color = getFaceColorByVector(arr[i], YLineAd);
        if (color != bottomColor) {
            return false;
        }
    }
    indexs = [6, 8, 26, 24];
    arr = getCubeByIndexs(indexs);
    for (var i = 0; i < arr.length; i++) {
        var color = getFaceColorByVector(arr[i], YLineAd);
        if (color == bottomColor) {
            return false;
        }
    }

    return true;
}
//第一步小白花
function step1() {


    if (checkStep1()) {
        console.log('start step2');
        currentStep = 2;
        step2();
        return;
    }

    step1Case1(0);
    step1Case1(1);
    step1Case1(2);
    step1Case1(3);

    step1Case2(0);
    step1Case2(1);
    step1Case2(2);
    step1Case2(3);

    step1Case3(0);
    step1Case3(1);
    step1Case3(2);
    step1Case3(3);

    step1Case4(0);
    step1Case4(1);
    step1Case4(2);
    step1Case4(3);

    if (!isRotating) {
        isAutoReset = false;
        console.log('something wrong in step1');
    }
}
//判断是否完成第一步小白花
function checkStep1() {
    var indexs = [1, 9, 11, 19];
    var step1 = true;
    for (var i = 0; i < indexs.length; i++) {
        var item = getCubeByIndex(indexs[i]);
        var color = getFaceColorByVector(item, YLine); //获取上表面颜色
        if (color != bottomColor) {
            step1 = false;
            break;
        }
    }
    return step1;
}
//小白花第一种情况
function step1Case1(rotateNum) {
    if (!isRotating) {
        var cube3 = getCubeByIndex(3, rotateNum);
        var cube9 = getCubeByIndex(9, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);

        if (getFaceColorByVector(cube3, zLine) == bottomColor) { //101、107
            if (getFaceColorByVector(cube9, YLine) != bottomColor) {
                l(rotateNum);
            } else {
                u(rotateNum);
            }
        }
    }
}
//小白花第二种情况
function step1Case2(rotateNum) {
    if (!isRotating) {
        var cube5 = getCubeByIndex(5, rotateNum);
        var cube11 = getCubeByIndex(11, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);

        if (getFaceColorByVector(cube5, zLine) == bottomColor) {
            if (getFaceColorByVector(cube11, YLine) != bottomColor) {
                R(rotateNum);
            } else {
                u(rotateNum);
            }
        }
    }
}
//小白花第三种情况
function step1Case3(rotateNum) {
    if (!isRotating) {
        var cube15 = getCubeByIndex(15, rotateNum);
        var cube9 = getCubeByIndex(9, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);

        if (getFaceColorByVector(cube15, YLineAd) == bottomColor) { //103、104
            if (getFaceColorByVector(cube9, YLine) != bottomColor) {
                l(rotateNum);
            } else {
                u(rotateNum);
            }
        }
    }
}
//小白花第四种情况
function step1Case4(rotateNum) {
    if (!isRotating) {
        var cube1 = getCubeByIndex(1, rotateNum);
        var cube7 = getCubeByIndex(7, rotateNum);
        var zLine = rotateAxisByYLine(ZLine, rotateNum);
        var xLine = rotateAxisByYLine(XLine, rotateNum);
        // zLine 是法向量吗
        // 是不是说 这个方块的 顶部颜色
        if (getFaceColorByVector(cube1, zLine) == bottomColor || getFaceColorByVector(cube7, zLine) == bottomColor) { //105、106
            if (getFaceColorByVector(cube1, YLine) != bottomColor) {
                F(rotateNum);
            } else {
                D(rotateNum)
            }
        }
    }
}
/**
 * 按顺序执行数组里边的方法
 * @param  {[type]}   arr       [方法数组]
 * @param  {[type]}   no        [当前执行方法序号]
 * @param  {[type]}   rotateNum [旋转次数]
 * @param  {Function} next      [所有方法执行完成之后回调]
 */
function runMethodAtNo(arr, no, rotateNum, next) {
    if (no >= arr.length - 1) {
        if (next) {
            // 这样子竟然是 跑了个函数
            arr[no](rotateNum, next);
        } else {
            arr[no](rotateNum);
        }
    } else {
        arr[no](rotateNum, function () {
            if (no < arr.length - 1) {
                no++
                runMethodAtNo(arr, no, rotateNum, next);
            }
        })
    }
}
/**
 * 魔方基本公式 U、F、L、D、R、u、f、l、d
 */
function U(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var zLine = rotateAxisByYLine(ZLine, rotateNum);
    var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
    normalize = zLine;
    rotateMove(cube2, xLineAd, next);
}

function u(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var xLine = rotateAxisByYLine(XLine, rotateNum);
    var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
    normalize = xLine;
    rotateMove(cube2, zLineAd, next);
}

function F(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var xLine = rotateAxisByYLine(XLine, rotateNum);
    normalize = xLine;
    rotateMove(cube2, YLineAd, next);
}

function f(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
    normalize = YLine;
    rotateMove(cube2, xLineAd, next)
}

function L(rotateNum, next) {
    stepCount++;
    var cube0 = getCubeByIndex(0, rotateNum);
    var zLine = rotateAxisByYLine(ZLine, rotateNum);
    normalize = zLine;
    rotateMove(cube0, YLineAd, next);
}

function l(rotateNum, next) {
    stepCount++;
    var cube0 = getCubeByIndex(0, rotateNum);
    var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
    normalize = YLine;
    rotateMove(cube0, zLineAd, next);
}

function D(rotateNum, next) {
    stepCount++;
    var cube8 = getCubeByIndex(8, rotateNum);
    var xLine = rotateAxisByYLine(XLine, rotateNum);
    var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
    normalize = xLine;
    rotateMove(cube8, zLineAd, next);
}

function d(rotateNum, next) {
    stepCount++;
    var cube8 = getCubeByIndex(8, rotateNum);
    var zLine = rotateAxisByYLine(ZLine, rotateNum);
    var xLineAd = rotateAxisByYLine(XLineAd, rotateNum);
    normalize = zLine;
    rotateMove(cube8, xLineAd, next);
}

function R(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var zLineAd = rotateAxisByYLine(ZLineAd, rotateNum);
    normalize = YLine;
    rotateMove(cube2, zLineAd, next);
}

function r(rotateNum, next) {
    stepCount++;
    var cube2 = getCubeByIndex(2, rotateNum);
    var zLine = rotateAxisByYLine(ZLine, rotateNum);
    normalize = zLine;
    rotateMove(cube2, YLineAd, next);
}

function B(rotateNum, next) {
    stepCount++;
    var cube20 = getCubeByIndex(20, rotateNum);
    var xLine = rotateAxisByYLine(XLine, rotateNum);
    normalize = xLine;
    rotateMove(cube20, YLine, next);
}

function b(rotateNum, next) {
    stepCount++;
    var cube20 = getCubeByIndex(20, rotateNum);
    var xLine = rotateAxisByYLine(XLine, rotateNum);
    normalize = xLine;
    rotateMove(cube20, YLineAd, next);
}
//根据索引素组获取方块
function getCubeByIndexs(indexs) {
    // 引索是 自定义的
    var arr = [];
    for (var i = 0; i < indexs.length; i++) {
        arr.push(getCubeByIndex(indexs[i]));
    }
    return arr;
}
/**
 * 根据索引获取方块
 * @param  index     索引
 * @param  rotateNum 旋转次数
 */
function getCubeByIndex(index, rotateNum) {
    var tempIndex = index;
    var tempRotateNum = rotateNum;
    while (rotateNum > 0) {
        if (parseInt(index / 9) == 0) {
            if (index % 3 == 0) {
                index += 2;
            } else if (index % 3 == 1) {
                index += 10;
            } else if (index % 3 == 2) {
                index += 18;
            }
        } else if (index % 3 == 2) {
            if (parseInt(index / 9) == 0) {
                index += 18;
            } else if (parseInt(index / 9) == 1) {
                index += 8;
            } else if (parseInt(index / 9) == 2) {
                index -= 2;
            }
        } else if (parseInt(index / 9) == 2) {
            if (index % 3 == 2) {
                index -= 2;
            } else if (index % 3 == 1) {
                index -= 10;
            } else if (index % 3 == 0) {
                index -= 18;
            }
        } else if (index % 3 == 0) {
            if (parseInt(index / 9) == 2) {
                index -= 18;
            } else if (parseInt(index / 9) == 1) {
                index -= 8;
            } else if (parseInt(index / 9) == 0) {
                index += 2;
            }
        }
        rotateNum--;
    }
    var cube;
    for (var i = 0; i < cubes.length; i++) {
        if (cubes[i].cubeIndex == index + minCubeIndex) {
            // 这里是利用 cubeIndex 所以是和之前不一样的吧
            // 所以是要 重新弄吧 要调用这个函数吧
            cube = cubes[i];
        }
    }
    return cube;
}
//根据Y轴旋转向量
function rotateAxisByYLine(vector, rotateNum) {
    // 可以选择是0 吗 这样返回他自己
    while (rotateNum > 0) {
        // 都是复制的
        if (vector.angleTo(XLine) == 0) {
            vector = ZLineAd.clone();
        } else if (vector.angleTo(ZLineAd) == 0) {
            vector = XLineAd.clone();
        } else if (vector.angleTo(XLineAd) == 0) {
            vector = ZLine.clone();
        } else if (vector.angleTo(ZLine) == 0) {
            vector = XLine.clone();
        }
        rotateNum--
    }
    return vector;
}
//根据颜色序号获取初始化时其对面颜色序号
function getOppositeColor(no) {
    if (no % 2 == 0 || no == 0) {
        return no + 1;
    } else {
        return no - 1;
    }
}
//获取法向量和已知向量方向相同的面的颜色序号
// 哪个是法向量
function getFaceColorByVector(cube, vector) {
    var materials = cube.material.materials;
    var faces = cube.geometry.faces;
    var normalMatrix = cube.normalMatrix;

    /**
     * 转换视角时摄像机位置发生了变动，模型开始上表面的法向量是世界坐标系的Y轴[1]，现在依然是世界坐标系的Y轴；
     * 但是小方块面的法向量乘以其法向量矩阵得到的是视图坐标系中的向量；
     * 世界坐标系转换成视图坐标系需要乘以视图矩阵的逆反矩阵。
     * [1]为什么不是 z轴
     */
    var viewMatrix = new THREE.Matrix4();
    viewMatrix.lookAt(camera.position, viewCenter, camera.up);
    viewMatrix.getInverse(viewMatrix);
    var tempVector = vector.clone();
    // 这里都会clone 的 所以应该没事吧
    tempVector.applyMatrix4(viewMatrix);
    var angles = [];

    for (var i = 0; i < faces.length; i++) {
        var tempNormal = faces[i].normal.clone();
        tempNormal.applyMatrix3(normalMatrix);
        /**
         * 按道理这里应该判断两向量夹角是否等于0，但是因为存在精度问题；
         * 有可能得到的角度很接近0，但却不等于0，另外不确定到底保留几位小数合适；
         * 因此使用判断最小值的方式。
         */
        angles.push(tempNormal.angleTo(tempVector));
    }
    var minNo = min(angles).no;
    return faces[minNo].materialIndex;
    //document.body.appendChild(materials[faces[minNo].materialIndex].map.image);
    //$frame.style.display = 'none';
}

window.requestAnimFrame = (function () { //如果有变化则可能还需要requestAnimationFrame刷新
    return window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.webkitRequestAnimationFrame;
})();

//根据页面宽度和高度创建渲染器，并添加容器中
var $frame = document.getElementById('canvas-frame');

function initThree() {
    width = window.innerWidth;
    height = window.innerHeight;
    renderer = new THREE.WebGLRenderer({
        antialias: true
    });
    renderer.setSize(width, height);
    renderer.setClearColor(0xFFFFFF, 1.0);
    $frame.appendChild(renderer.domElement);
}

//创建相机，并设置正方向和中心点
var camera;
var controller; //视角控制器
var viewCenter = new THREE.Vector3(0, 0, 0);

function initCamera() {
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 1000);
    camera.position.set(0, 0, 600);
    camera.up.set(0, 1, 0); //正方向
    camera.lookAt(viewCenter);
}

//创建场景，后续元素需要加入到场景中才会显示出来
var scene;

function initScene() {
    scene = new THREE.Scene();
}

//创建光线
var light;

function initLight() {
    light = new THREE.AmbientLight(0xfefefe);
    scene.add(light);
}

/**
 * 简易魔方
 * x、y、z 魔方中心点坐标
 * num 魔方阶数
 * len 小方块宽高
 * colors 魔方六面体颜色
 */
function SimpleCube(x, y, z, num, len, colors) {
    //魔方左上角坐标
    var leftUpX = x - num / 2 * len;
    var leftUpY = y + num / 2 * len;
    var leftUpZ = z + num / 2 * len;

    //根据颜色生成材质
    var materialArr = [];
    for (var i = 0; i < colors.length; i++) {
        var texture = new THREE.Texture(faces(colors[i]));
        texture.needsUpdate = true;
        var material = new THREE.MeshLambertMaterial({
            map: texture
        });
        materialArr.push(material);
    }

    var cubes = [];
    for (var i = 0; i < num; i++) {
        for (var j = 0; j < num * num; j++) {
            var cubegeo = new THREE.BoxGeometry(len, len, len);
            var cube = new THREE.Mesh(cubegeo, materialArr);

            //依次计算各个小方块中心点坐标
            cube.position.x = (leftUpX + len / 2) + (j % num) * len;
            cube.position.y = (leftUpY - len / 2) - parseInt(j / num) * len;
            cube.position.z = (leftUpZ - len / 2) - i * len;
            cubes.push(cube)
        }
    }
    return cubes;
}

//生成canvas素材
function faces(rgbaColor) {
    var canvas = document.createElement('canvas');
    canvas.width = 256;
    canvas.height = 256;
    var context = canvas.getContext('2d');
    if (context) {
        //画一个宽高都是256的黑色正方形
        canvas.setAttribute('color', rgbaColor);
        context.fillStyle = 'rgba(0,0,0,1)';
        context.fillRect(0, 0, 256, 256);
        //在内部用某颜色的16px宽的线再画一个宽高为224的圆角正方形并用改颜色填充
        context.rect(16, 16, 224, 224);
        context.lineJoin = 'round';
        context.lineWidth = 16;
        context.fillStyle = rgbaColor;
        context.strokeStyle = rgbaColor;
        context.stroke();
        context.fill();
    } else {
        alert('您的浏览器不支持Canvas无法预览.\n');
    }
    return canvas;
}

//创建展示场景所需的各种元素
var cubes

function initObject() {
    //生成魔方小正方体
    cubes = SimpleCube(CubeParams.x, CubeParams.y, CubeParams.z, CubeParams.num, CubeParams.len, CubeParams.colors);
    var ids = [];
    for (var i = 0; i < cubes.length; i++) {
        var item = cubes[i];
        /**
         * 由于筛选运动元素时是根据物体的id规律来的，但是滚动之后位置发生了变化；
         * 再根据初始规律筛选会出问题，而且id是只读变量；
         * 所以这里给每个物体设置一个额外变量cubeIndex，每次滚动之后更新根据初始状态更新该cubeIndex；
         * 让该变量一直保持初始规律即可。
         */
        initStatus.push({
            x: item.position.x,
            y: item.position.y,
            z: item.position.z,
            cubeIndex: item.id
        });
        item.cubeIndex = item.id;
        ids.push(item.id);
        // 确实  是那几个方块
        scene.add(cubes[i]); //并依次加入到场景中
    }
    minCubeIndex = min(ids).value;

    //透明正方体
    var cubegeo = new THREE.BoxGeometry(150, 150, 150);
    var hex = 0x000000;
    for (var i = 0; i < cubegeo.faces.length; i += 2) {
        cubegeo.faces[i].color.setHex(hex);
        cubegeo.faces[i + 1].color.setHex(hex);
    }
    var cubemat = new THREE.MeshBasicMaterial({
        vertexColors: THREE.FaceColors,
        opacity: 0,
        transparent: true
    });
    var cube = new THREE.Mesh(cubegeo, cubemat);
    cube.cubeType = 'coverCube';
    scene.add(cube);
}

//渲染
function render() {
    renderer.clear();
    renderer.render(scene, camera);
    window.requestAnimFrame(render);
}

//开始
function threeStart() {
    initThree();
    initCamera();
    initScene();
    initLight();
    initObject();
    render();
    //监听鼠标事件
    // 渲染器
    // 这是不是 鼠标 按下去 就 转动
    renderer.domElement.addEventListener('mousedown', startCube, false);
    renderer.domElement.addEventListener('mousemove', moveCube, false);
    renderer.domElement.addEventListener('mouseup', stopCube, false);
    //监听触摸事件
    renderer.domElement.addEventListener('touchstart', startCube, false);
    renderer.domElement.addEventListener('touchmove', moveCube, false);
    renderer.domElement.addEventListener('touchend', stopCube, false);
    //视角控制
    controller = new THREE.OrbitControls(camera, renderer.domElement);
    controller.target = viewCenter; //设置控制点

    //自动还原一
    var $autoResetV1 = document.querySelector('#autoResetV1');
    $autoResetV1.addEventListener('click', function () {
        autoResetV1(cubes)
    }, false);

    //随机旋转
    var $randomRotate = document.querySelector('#randomRotate');
    $randomRotate.addEventListener('click', function () {
        randomRotate();

        // aa=takeChargeAsChiefOf();
        // console.log("aa")
        // console.log(aa)

    }, false);

    setTimeout(()=>{

        aa=takeChargeAsChiefOf();
        console.log("aa")
        console.log(aa)
    },10000);

    // aa=getCubeByIndex(20);
    // console.log("aa")
    // console.log(aa)

    // aa=takeChargeAsChiefOf();
    // console.log("aa")
    // console.log(aa)

    // let cubeLst = getCubeLst(sliceZ1);

    // sideSameColor(ZLine, getCubeLst(sliceZ1))
}

//魔方操作结束
function stopCube() {
    // console.log("intersect");
    // // 打印这个 怎么那么耗时
    // console.log(intersect);
    intersect = null;
    startPoint = null
}

//绕着世界坐标系的某个轴旋转
function rotateAroundWorldY(obj, rad) {
    var x0 = obj.position.x;
    var z0 = obj.position.z;
    /**
     * 因为物体本身的坐标系是随着物体的变化而变化的，
     * 所以如果使用rotateZ、rotateY、rotateX等方法，
     * 多次调用后就会出问题，先改为Quaternion实现。
     */
    var q = new THREE.Quaternion();
    q.setFromAxisAngle(new THREE.Vector3(0, 1, 0), rad);
    obj.quaternion.premultiply(q);
    //obj.rotateY(rad);
    obj.position.x = Math.cos(rad) * x0 + Math.sin(rad) * z0;
    obj.position.z = Math.cos(rad) * z0 - Math.sin(rad) * x0;
}

function rotateAroundWorldZ(obj, rad) {
    var x0 = obj.position.x;
    var y0 = obj.position.y;
    var q = new THREE.Quaternion();
    q.setFromAxisAngle(new THREE.Vector3(0, 0, 1), rad);
    obj.quaternion.premultiply(q);
    //obj.rotateZ(rad);
    obj.position.x = Math.cos(rad) * x0 - Math.sin(rad) * y0;
    obj.position.y = Math.cos(rad) * y0 + Math.sin(rad) * x0;
}

function rotateAroundWorldX(obj, rad) {
    var y0 = obj.position.y;
    var z0 = obj.position.z;
    var q = new THREE.Quaternion();
    q.setFromAxisAngle(new THREE.Vector3(1, 0, 0), rad);
    obj.quaternion.premultiply(q);
    //obj.rotateX(rad);
    obj.position.y = Math.cos(rad) * y0 - Math.sin(rad) * z0;
    obj.position.z = Math.cos(rad) * z0 + Math.sin(rad) * y0;
}

//滑动操作魔方
function moveCube(event) {
    getIntersects(event);
    if (intersect) {
        if (!isRotating && startPoint) { //魔方没有进行转动且满足进行转动的条件
            // 刚才记录了一个 开始的位置 startPoint
            movePoint = intersect.point;
            // 现在这个 point  是松手的位置吗
            if (!movePoint.equals(startPoint)) { //和起始点不一样则意味着可以得到转动向量了
                var sub = movePoint.sub(startPoint); //计算转动向量
                rotateMove(intersect.object, sub);
                // 没有传入 next 
            }
        }
    }
    event.preventDefault();
}

// 文档：就是 9个 方格吧 我刚才拉动的 右边的....
// 链接：http://note.youdao.com/noteshare?id=78f45b657a3326a518c62307bc19152c&sub=8994D21D5C934690A8F2CCCF9399208E
//某方块在某个方向转动
function rotateMove(target, vector, next) {
    // next 不知是什么
    // vector 是向量 
    isRotating = true; //转动标识置为true
    var direction = getDirection(vector); //获得方向
    //   console.log("direction");
    //   console.log(direction);
    //   方向也不知道什么 数学
    var elements = getBoxs(target, direction);
    //   他是 封装的 是不是意味着 我改不了
    // 虽然我也不会 改 这是数学！！
    // console.log("elements");
    // console.log(elements);
    window.requestAnimFrame(function (timestamp) {
        rotateAnimation(elements, direction, timestamp, 0, null, next);
    });
}

/**
 * 旋转动画
 */
function rotateAnimation(elements, direction, currentstamp, startstamp, laststamp, next) {
    var totalTime = 200; //转动的总运动时间
    var isLastRotate = false; //是否是某次转动最后一次动画
    if (startstamp === 0) {
        startstamp = currentstamp;
        laststamp = currentstamp;
    }
    if (currentstamp - startstamp >= totalTime) {
        currentstamp = startstamp + totalTime;
        isLastRotate = true;
    }
    switch (direction) {
        //绕z轴顺时针
        case 0.1:
        case 1.2:
        case 2.4:
        case 3.3:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldZ(elements[i], -90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
            //绕z轴逆时针
        case 0.2:
        case 1.1:
        case 2.3:
        case 3.4:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldZ(elements[i], 90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
            //绕y轴顺时针
        case 0.4:
        case 1.3:
        case 4.3:
        case 5.4:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldY(elements[i], -90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
            //绕y轴逆时针
        case 1.4:
        case 0.3:
        case 4.4:
        case 5.3:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldY(elements[i], 90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
            //绕x轴顺时针
        case 2.2:
        case 3.1:
        case 4.1:
        case 5.2:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldX(elements[i], 90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
            //绕x轴逆时针
        case 2.1:
        case 3.2:
        case 4.2:
        case 5.1:
            for (var i = 0; i < elements.length; i++) {
                rotateAroundWorldX(elements[i], -90 * Math.PI / 180 * (currentstamp - laststamp) / totalTime);
            }
            break;
        default:
            break;
    }
    if (!isLastRotate) {
        window.requestAnimFrame(function (timestamp) {
            rotateAnimation(elements, direction, timestamp, startstamp, currentstamp, next);
        });
    } else {
        isRotating = false;
        startPoint = null;
        updateCubeIndex(elements);
        if (next) {
            next();
        } else {
            if (isAutoReset) {
                switch (currentStep) {
                    case 1:
                        step1();
                        break;
                    case 2:
                        step2();
                        break;
                    case 3:
                        step3();
                        break;
                    case 4:
                        step4();
                        break;
                    case 5:
                        step5();
                        break;
                    case 6:
                        step6();
                        break;
                    case 7:
                        step7();
                        break;
                    case 8:
                        step8();
                        break;
                    default:
                        break;
                }
            }
        }
    }
}

//更新位置索引
function updateCubeIndex(elements) {
    for (var i = 0; i < elements.length; i++) {
        var temp1 = elements[i];
        for (var j = 0; j < initStatus.length; j++) {
            var temp2 = initStatus[j];
            if (Math.abs(temp1.position.x - temp2.x) <= CubeParams.len / 2 &&
                Math.abs(temp1.position.y - temp2.y) <= CubeParams.len / 2 &&
                Math.abs(temp1.position.z - temp2.z) <= CubeParams.len / 2) {
                temp1.cubeIndex = temp2.cubeIndex;
                temp1.skipNext = false;
                break;
            }
        }
    }
}

//根据方向获得运动元素
function getBoxs(target, direction) {
    var targetId = target.cubeIndex;
    targetId = targetId - minCubeIndex;
    var numI = parseInt(targetId / 9);
    var numJ = targetId % 9;
    var boxs = [];
    //根据绘制时的规律判断 no = i*9+j
    switch (direction) {
        //绕z轴
        case 0.1:
        case 0.2:
        case 1.1:
        case 1.2:
        case 2.3:
        case 2.4:
        case 3.3:
        case 3.4:
            for (var i = 0; i < cubes.length; i++) {
                var tempId = cubes[i].cubeIndex - minCubeIndex;
                if (numI === parseInt(tempId / 9)) {
                    boxs.push(cubes[i]);
                }
            }
            break;
            //绕y轴
        case 0.3:
        case 0.4:
        case 1.3:
        case 1.4:
        case 4.3:
        case 4.4:
        case 5.3:
        case 5.4:
            for (var i = 0; i < cubes.length; i++) {
                var tempId = cubes[i].cubeIndex - minCubeIndex;
                if (parseInt(numJ / 3) === parseInt(tempId % 9 / 3)) {
                    boxs.push(cubes[i]);
                }
            }
            break;
            //绕x轴
        case 2.1:
        case 2.2:
        case 3.1:
        case 3.2:
        case 4.1:
        case 4.2:
        case 5.1:
        case 5.2:
            for (var i = 0; i < cubes.length; i++) {
                var tempId = cubes[i].cubeIndex - minCubeIndex;
                if (tempId % 9 % 3 === numJ % 3) {
                    boxs.push(cubes[i]);
                }
            }
            break;
        default:
            break;
    }
    return boxs;
}

//获得旋转方向
function getDirection(vector3) {
    var direction;
    //判断差向量和x、y、z轴的夹角
    var xAngle = vector3.angleTo(XLine);
    var xAngleAd = vector3.angleTo(XLineAd);
    var yAngle = vector3.angleTo(YLine);
    var yAngleAd = vector3.angleTo(YLineAd);
    var zAngle = vector3.angleTo(ZLine);
    var zAngleAd = vector3.angleTo(ZLineAd);
    // 差距 向量是什么
    var minAngle = min([xAngle, xAngleAd, yAngle, yAngleAd, zAngle, zAngleAd]).value; //最小夹角

    switch (minAngle) {
        case xAngle:
            // 这是自定义的 方向
            // 为什么会是 4.1 
            direction = 0; //向x轴正方向旋转90度（还要区分是绕z轴还是绕y轴）
            if (normalize.equals(YLine)) {
                direction = direction + 0.1; //绕z轴顺时针
            } else if (normalize.equals(YLineAd)) {
                direction = direction + 0.2; //绕z轴逆时针
            } else if (normalize.equals(ZLine)) {
                direction = direction + 0.3; //绕y轴逆时针
            } else {
                direction = direction + 0.4; //绕y轴顺时针
            }
            break;
        case xAngleAd:
            direction = 1; //向x轴反方向旋转90度
            if (normalize.equals(YLine)) {
                direction = direction + 0.1; //绕z轴逆时针
            } else if (normalize.equals(YLineAd)) {
                direction = direction + 0.2; //绕z轴顺时针
            } else if (normalize.equals(ZLine)) {
                direction = direction + 0.3; //绕y轴顺时针
            } else {
                direction = direction + 0.4; //绕y轴逆时针
            }
            break;
        case yAngle:
            direction = 2; //向y轴正方向旋转90度
            if (normalize.equals(ZLine)) {
                direction = direction + 0.1; //绕x轴逆时针
            } else if (normalize.equals(ZLineAd)) {
                direction = direction + 0.2; //绕x轴顺时针
            } else if (normalize.equals(XLine)) {
                direction = direction + 0.3; //绕z轴逆时针
            } else {
                direction = direction + 0.4; //绕z轴顺时针
            }
            break;
        case yAngleAd:
            direction = 3; //向y轴反方向旋转90度
            if (normalize.equals(ZLine)) {
                direction = direction + 0.1; //绕x轴顺时针
            } else if (normalize.equals(ZLineAd)) {
                direction = direction + 0.2; //绕x轴逆时针
            } else if (normalize.equals(XLine)) {
                direction = direction + 0.3; //绕z轴顺时针
            } else {
                direction = direction + 0.4; //绕z轴逆时针
            }
            break;
        case zAngle:
            direction = 4; //向z轴正方向旋转90度
            if (normalize.equals(YLine)) {
                // 哦 这里有 加 +0.1
                direction = direction + 0.1; //绕x轴顺时针
            } else if (normalize.equals(YLineAd)) {
                direction = direction + 0.2; //绕x轴逆时针
            } else if (normalize.equals(XLine)) {
                direction = direction + 0.3; //绕y轴顺时针
            } else {
                direction = direction + 0.4; //绕y轴逆时针
            }
            break;
        case zAngleAd:
            direction = 5; //向z轴反方向旋转90度
            if (normalize.equals(YLine)) {
                direction = direction + 0.1; //绕x轴逆时针
            } else if (normalize.equals(YLineAd)) {
                direction = direction + 0.2; //绕x轴顺时针
            } else if (normalize.equals(XLine)) {
                direction = direction + 0.3; //绕y轴逆时针
            } else {
                direction = direction + 0.4; //绕y轴顺时针
            }
            break;
        default:
            break;
    }
    return direction;
}

//获取数组中的最小值
function min(arr) {
    var min = arr[0];
    var no = 0;
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] < min) {
            min = arr[i];
            no = i;
        }
    }
    return {
        no: no,
        value: min
    };
}

//是否存在重复值
function isRepeat(arr) {
    arr.sort(function (a, b) {
        if (a < b) {
            return -1;
        }
        if (a > b) {
            return 1;
        }
        return 0;
    });
    for (var i = 0; i < arr.length - 1; i++) {
        if (arr[i] == arr[i + 1]) {
            return true;
        }
    }
    return false;
}

//开始操作魔方
function startCube(event) {
    getIntersects(event);
    //魔方没有处于转动过程中且存在碰撞物体
    // 相交 intersect
    // 什么是碰撞物体
    if (!isRotating && intersect) {
        startPoint = intersect.point; //开始转动，设置起始点
        // 碰撞点？
        // 这个变量 只有这里有。。
        // 视角 哦 不对 这是框架里的 所以不是我们调用 而是他框架里有用
        controller.enabled = false; //当刚开始的接触点在魔方上时操作为转动魔方，屏蔽控制器转动
    } else {
        controller.enabled = true; //当刚开始的接触点没有在魔方上或者在魔方上但是魔方正在转动时操作转动控制器
    }
}

//获取操作焦点以及该焦点所在平面的法向量
function getIntersects(event) {
    //触摸事件和鼠标事件获得坐标的方式有点区别
    if (event.touches) {
        var touch = event.touches[0];
        mouse.x = (touch.clientX / width) * 2 - 1;
        mouse.y = -(touch.clientY / height) * 2 + 1;
    } else {
        mouse.x = (event.clientX / width) * 2 - 1;
        mouse.y = -(event.clientY / height) * 2 + 1;
    }
    raycaster.setFromCamera(mouse, camera);
    //Raycaster方式定位选取元素，可能会选取多个，以第一个为准
    // https://blog.csdn.net/ithanmang/article/details/80897888
    // https://blog.csdn.net/ithanmang/article/details/80897888
    // 被击中的对象 是一个小的方块 还是
    var intersects = raycaster.intersectObjects(scene.children);
    // intersects 可以画出来吗
    // 相交于 那些方块
    // console.log("intersects");
    // console.log(intersects);
    // 打印 巨花时间
    if (intersects.length) {
        try {
            // 只有 在魔方上 拉动才会有差向量
            // 最近的那个
            // 覆盖立方体
            //   这样的话 假如 他是 斜着的 然后去点击那个图，他怎么知道是什么呢
            if (intersects[0].object.cubeType === 'coverCube') {
                intersect = intersects[1];
                // 他就是第二靠近的那个
                //   法向量？
                normalize = intersects[0].face.normal;
            } else {
                intersect = intersects[0];
                // 正则？ 归一化？
                normalize = intersects[1].face.normal;
            }
        } catch (err) {
            //nothing
        }
    }
}

// lst=[]
// // sliceZ3
// sliceX1.forEach(o=>{
//     // lst.push(o-2)
//     lst.push(o-1)
//     // console.log(o-2);
// })
// console.log(lst)

// lst=[]
//
// sliceZ3.forEach(o=>{
//     // lst.push(o-2)
//     // lst.push(o-1)
//     lst.push(o-9)
//     // console.log(o-2);
// })
// console.log(lst)

// lst=[]
//
// sliceZ3.forEach(o=>{
//     // lst.push(o-2)
//     // lst.push(o-1)
//     lst.push(o-18)
//     // console.log(o-2);
// })
// console.log(lst)

// lst=[]
// lst2=[]
//
// sliceY1.forEach(o=>{
//     // lst.push(o-2)
//     // lst.push(o-1)
//     // lst.push(o-18)
//     lst.push(o+3)
//     lst2.push(o+6)
//     // console.log(o-2);
// })
// console.log(lst)
// console.log(lst2)

// a=takeChargeAsChiefOf();
// console.log("a")
// console.log(a)

